#region Copyright Notice
// 
// 
//  
//  Copyright (c) 2009-2011 Anindya Chatterjee
//  
//  Licensed under the Apache License, Version 2.0 (the "License");
//  you may not use this file except in compliance with the License.
//  You may obtain a copy of the License at
//  
//      http://www.apache.org/licenses/LICENSE-2.0
//  
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS,
//  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//  See the License for the specific language governing permissions and
//  limitations under the License.
// 
// 
#endregion
using System.Collections.Generic;
using System.Linq;
using AbstractClass.Collections.Graph;
using NUnit.Framework;

namespace QuasarTest.Core
{
    [TestFixture]
    public class GraphTest
    {
        private Graph<int> _graph;

        [TestFixtureSetUp]
        public void Init()
        {
            _graph = new Graph<int>();
            for (int i = 0; i < 10; i++)
            {
                _graph.Add(i);
            }
            for (int i = 0; i < 8; i++)
            {
                _graph.AddUndirectedEdge(i, i + 2, i * i);
            }
            for (int i = 0; i < 9; i++)
            {
                _graph.AddDirectedEdge(i, i + 1, i + i);
            }
            _graph.AddUndirectedEdge(9, 9, 3);
            _graph.AddDirectedEdge(6, 7, 7);
            _graph.AddDirectedEdge(6, 8, 30);
        }

        [Test]
        public void Test01SpanningTree()
        {
            Graph<int> graphB = _graph.ExecuteAlgorithm(new MinimalSpanningTree<int>());

            Assert.AreNotEqual(graphB.NodeList.First(), _graph.NodeList.First());
            Assert.Less(graphB.Edges.Count, _graph.Edges.Count);
            Assert.AreEqual(graphB.NodeList.Count, _graph.NodeList.Count);
            Assert.AreEqual(graphB.NodeList.All(x => x.Loops.Count() == 0), true);

            for (int i = 0; i < _graph.NodeList.Count; i++)
            {
                GraphNode<int> nodeOne = _graph.FindNode(i);
                GraphNode<int> nodeTwo = graphB.FindNode(i);

                Assert.LessOrEqual(nodeTwo.Edges.Count(), nodeOne.Edges.Count());
                Assert.LessOrEqual(nodeTwo.Edges.Max(x => x.Cost), nodeOne.Edges.Max(x => x.Cost));
            }
        }

        [Test]
        public void Test02GeneralGraphOperation()
        {
            Assert.AreEqual(_graph.Count, 10);
            GraphEdge<int> edge = _graph.GetEdges(0, 1).FirstOrDefault();
            Assert.IsTrue(edge.IsDirected);
            edge = _graph.GetEdges(0, 2).FirstOrDefault();
            Assert.IsFalse(edge.IsDirected);
            Assert.IsTrue(_graph.Contains(0));
            Assert.IsTrue(_graph.ContainsEdge(0, 1));
            Assert.IsTrue(_graph.ContainsEdge(0, 1, 0));
            Assert.IsFalse(_graph.ContainsEdge(0, 1, 1));

            GraphNode<int> nodeFrom = _graph.FindNode(0);
            GraphNode<int> nodeTo = _graph.FindNode(1);
            Assert.True(_graph.ContainsEdge(nodeFrom, nodeTo));
            Assert.True(_graph.ContainsEdge(nodeFrom, nodeTo, 0));
            Assert.False(_graph.ContainsEdge(nodeFrom, nodeTo, 1));

            Assert.IsTrue(_graph.GetEdges(2, 4, 4).Single().Cost == 4);
            Assert.IsFalse(_graph.IsDirectedGraph);
            Assert.IsTrue(_graph.Order == 10);
            Assert.IsTrue(_graph.Size == 20);
        }

        [Test]
        public void Test03GraphRemoval()
        {
            Assert.IsTrue(_graph.Remove(0));
            Assert.IsFalse(_graph.Contains(0));
            Assert.IsFalse(_graph.ContainsEdge(0, 1));
            Assert.IsFalse(_graph.ContainsEdge(0, 2));

            GraphNode<int> node = _graph.FindNode(1);
            Assert.IsTrue(_graph.Remove(node));
            Assert.IsFalse(_graph.Contains(node));

            IEnumerable<GraphEdge<int>> edge1 = _graph.GetEdges(5, 6);
            GraphEdge<int> x = edge1.First();
            Assert.IsTrue(_graph.RemoveEdge(5, 6));
            Assert.IsFalse(_graph.ContainsEdge(x));

            IEnumerable<GraphEdge<int>> edge2 = _graph.GetEdges(5, 7);
            x = edge2.First();
            Assert.IsTrue(_graph.RemoveEdge(x));
            Assert.IsFalse(_graph.ContainsEdge(x));
            Assert.IsFalse(_graph.RemoveEdge(5, 7));

            IEnumerable<GraphEdge<int>> edge3 = _graph.GetEdges(6, 7);
            Assert.IsTrue(edge3.Count() == 2);
            Assert.IsTrue(_graph.RemoveEdge(6, 7, 7));
            Assert.IsTrue(edge3.Count() == 1);
            Assert.IsTrue(edge3.First().Cost == 12);

            GraphNode<int> node1 = _graph.FindNode(8);
            GraphNode<int> node2 = _graph.FindNode(9);
            Assert.IsTrue(_graph.RemoveEdge(node1, node2));
            Assert.IsFalse(_graph.ContainsEdge(node1, node2));

            node1 = _graph.FindNode(9);
            node2 = _graph.FindNode(9);
            Assert.IsFalse(_graph.RemoveEdge(node1, node2, 9));
            Assert.IsTrue(_graph.RemoveEdge(node1, node2, 3));

            IEnumerable<GraphEdge<int>> edges = _graph.GetEdges(6, 8);
            Assert.IsTrue(edges.Count() == 2);
            Assert.IsTrue(_graph.RemoveEdges(edges));
            Assert.IsTrue(edges.Count() == 0);
            Assert.IsFalse(_graph.ContainsEdge(6, 8));
        }

        [Test]
        public void TestClear()
        {
            _graph.Clear();
            Assert.AreEqual(_graph.Count, 0);
            Assert.AreEqual(_graph.Edges.Count, 0);
            Assert.AreEqual(_graph.NodeList.Count, 0);
        }
    }
}